﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Mindfor.Web.Data;
using Mindfor.Web.Routing;
using NHibernate;
using NHibernate.Linq;
using Mindfor.Web.Models;
using Mindfor.Web.Features;

namespace Mindfor.Web.Modules.News.Controllers
{
	public class NewsController : CmsController
	{
		/// <summary>
		/// New item creating page.
		/// </summary>
		[HttpGet]
		[CmsAuthorize(NewsModule.NewsRole)]
		[UrlSubAction("IndexAdmin")]
		[UrlRoute("Add", Path="Admin/News")]
		[LoadModelState]
		[ReturnUrlEnable]
		public ActionResult Add()
		{
			return Edit(null);
		}

		/// <summary>
		/// News item creating 'POST'-method.
		/// </summary>
		[HttpPost]
		[ValidateInput(false)]
		public ActionResult Add([Bind(Exclude = "Image")]NewsItem model, int? imageType)
		{
			return Edit(null, model, imageType);
		}

		/// <summary>
		/// News item editing page.
		/// </summary>
		[HttpGet]
		[UrlSubAction("IndexAdmin")]
		[UrlRoute("{id}/Edit", Path="Admin/News")]
		[UrlRouteConstraint("id", Constraints.IsInt)]
		[CmsAuthorize(NewsModule.NewsRole)]
		[LoadModelState]
		[ReturnUrlEnable]
		public ActionResult Edit(int? id)
		{
			// get item
			if (id.HasValue)
			{
				NewsItem item = Data.Get<NewsItem>(id.Value);
				if (item == null)
					return HttpNotFound();
				else
					item.Date = item.Date.ToLocalTime();
				ViewData.Model = item;
			}
			else
			{
				ModelState.SetDefaultModelValue("Date", DateTime.Now);
			}

			// create folder
			Folder folder = Data.Query<Folder>().FirstOrDefault(r => r.Name == Module.Name && r.Parent == null);
			if (folder == null)
			{
				folder = new Folder(Module.Name);
				using (ITransaction t = Data.BeginTransaction())
				{
					Data.Save(folder);
					t.Commit();
				}
			}
			ViewData["Folder"] = folder;
			return View("Edit");
		}

		/// <summary>
		/// News item editing 'POST'-method.
		/// </summary>
		[HttpPost]
		[CmsAuthorize(NewsModule.NewsRole)]
		[ValidateInput(false)]
		public ActionResult Edit(int? id, [Bind(Exclude="Image")]NewsItem model, int? imageType)
		{
			// is model is valid
			if (ModelState.IsValid)
			{
				model = Data.MergeEntity(model);
				if (id.HasValue && model.Id != id.Value)
					return HttpNotFound();
				model.Date = model.Date.ToUniversalTime();

				// typograf texts
				model.ShortText = Typograf.ProcessText(model.ShortText, TypografEntityTypes.HtmlEntities);
				if (!String.IsNullOrEmpty(model.FullText))
					model.FullText = Typograf.ProcessText(model.FullText, TypografEntityTypes.HtmlEntities);

				// load image
				switch (imageType)
				{
					// insert new image
					case null:
					case 0:
						if (Request.Files["Image"] != null)
							model.Image = Request.Files["Image"].GetBytes();
						break;
					// delete
					case 1:
						model.Image = null;
						break;
				};

				// submit changes
				using (ITransaction t = Data.BeginTransaction())
				{
					Data.SaveOrUpdate(model);
					t.Commit();
				}
				
				// setup media folder
				//if (Request.Form["FolderId"] != null)
				//{
				//    int folderId = int.Parse(Request.Form["FolderId"]);
				//    IFolder folder = Data.Media.GetFolder(folderId);
				//    if (folder != null)
				//    {
				//        @new.FolderId = folderId;
				//        folder.Name = "New" + @new.Id;
				//        folder.IsTemp = false;
				//        folder.UserId = null;
				//    }

				//    // need to save new post's folder id
				//    DataAlt.SubmitChanges();
				//    // need to save new folder's name
				//    Data.SubmitChanges();
				//}

				return RedirectToAction("Item", new { id = model.Id });
			}

			this.SaveModelState();
			return RedirectToAction(id == null ? "Add" : "Edit");
		}

		/// <summary>
		/// Delete news item.
		/// </summary>
		/// <param name="id">News item id.</param>
		[HttpGet]
		[UrlSubAction("IndexAdmin")]
		[UrlRoute("{id}/Delete", Path="Admin/News")]
		[UrlRouteConstraint("id", Constraints.IsInt)]
		[CmsAuthorize(NewsModule.NewsRole)]
		[ReturnUrlEnable]
		public ActionResult Delete(int id)
		{
			// get news
			NewsItem newsItem = Data.Get<NewsItem>(id);
			if (newsItem == null)
				return HttpNotFound();

			// delete
			using (ITransaction t = Data.BeginTransaction())
			{
				Data.Delete(newsItem);
				t.Commit();
			}
			
			// return
			return RedirectToAction("IndexAdmin", new { page = 1 });
		}

		/// <summary>
		/// Returns PageResult which renders news index view.
		/// </summary>
		/// <param name="page">Page number.</param>
		/// <returns>PageResult.</returns>
		[UrlRoute(1, "")]
		[UrlRouteDefault(1, "page", 1)]
		[UrlRoute(2, "Page{page}")]
		[UrlRouteConstraint(2, "page", Constraints.IsInt)]
		public ActionResult Index(int page)
		{
			// get news
			int pageSize = 20;
			int pageIndex = page - 1;
			if (pageIndex < 0)
				return HttpNotFound();

			IQueryable<NewsItem> newsQuery = Data.Query<NewsItem>()
				.OrderByDescending(r => r.IsFixed)
				.ThenByDescending(r => r.Date);

			ViewData.Model = newsQuery.Skip(pageIndex * pageSize).Take(pageSize).ToList();
			ViewData["Pager"] = new PagerModel(newsQuery.Count(), pageSize);
			ViewData["IsEditable"] = User != null && User.IsInRole(CmsRoles.Administrator, NewsModule.NewsRole);

			return View();
		}

		/// <summary>
		/// Returns PageResult which renders news Admin index view.
		/// </summary>
		/// <param name="page">Page number.</param>
		/// <returns>PageResult.</returns>
		[UrlRoute(1, "", Path="Admin/News")]
		[UrlRouteDefault(1, "page", 1)]
		[UrlRoute(2, "Page{page}", Path="Admin/News")]
		[UrlRouteConstraint(2, "page", Constraints.IsInt)]
		[AdminLink("Новости", "Сайт")]
		[CmsAuthorize(NewsModule.NewsRole)]
		public ActionResult IndexAdmin(int page)
		{
			// get news
			int pageSize = 20;
			int pageIndex = page - 1;
			if (pageIndex < 0)
				return HttpNotFound();

			IQueryable<NewsItem> newsQuery = Data.Query<NewsItem>()
				.OrderByDescending(r => r.IsFixed)
				.ThenByDescending(r => r.Date);

			ViewData.Model = newsQuery.Skip(pageIndex * pageSize).Take(pageSize).ToList();
			ViewData["Pager"] = new PagerModel(newsQuery.Count(), pageSize);

			return View();
		}

		/// <summary>
		/// Returns PageResult which renders one full newsItem view.
		/// </summary>
		/// <param name="id">NewsItem Id.</param>
		/// <returns>PageResult.</returns>
		[HttpGet]
		[UrlRoute("{id}")]
		[UrlRouteConstraint("id", Constraints.IsInt)]
		[ReturnUrlEnable]
		public ActionResult Item(int id)
		{
			// get news
			NewsItem item = Data.Get<NewsItem>(id);
			if (item == null)
				return HttpNotFound();
			
			//TODO if nothing to do: ReturnUrl should returns us to concrete index page which the item belongs

			// return view
			ViewData.Model = item;
			ViewData["IsEditable"] = User != null && User.IsInRole(CmsRoles.Administrator, NewsModule.NewsRole);
			ViewData["ReturnUrl"] = Url.Action("Index");
			return View();
		}

		[Widget("News")]
		public ActionResult NewsWidget()
		{
			// get news
			int pageSize = 5;			
			IQueryable<NewsItem> newsQuery = Data.Query<NewsItem>()
				.OrderByDescending(r => r.IsFixed)
				.ThenByDescending(r => r.Date);

			ViewData.Model = newsQuery.Take(pageSize).ToList();
			return PartialView();
		}
	}
}